#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {
  if (*(int*)a > *(int*)b)
    return 1;
  if (*(int*)a < *(int*)b)
    return -1;
  return 0;
}

struct gameState* newGame() {
  struct gameState* g = malloc(sizeof(struct gameState));
  return g;
}

int* kingdomCards(int k1, int k2, int k3, int k4, int k5, int k6, int k7,
		  int k8, int k9, int k10) {
  int* k = malloc(10 * sizeof(int));
  k[0] = k1;
  k[1] = k2;
  k[2] = k3;
  k[3] = k4;
  k[4] = k5;
  k[5] = k6;
  k[6] = k7;
  k[7] = k8;
  k[8] = k9;
  k[9] = k10;
  return k;
}

int initializeGame(int numPlayers, int kingdomCards[10], int randomSeed,
		   struct gameState *state) {

  int i;
  int j;
  int it;			
  //set up random number generator
  SelectStream(1);
  PutSeed((long)randomSeed);
  
  //check number of players
  if (numPlayers > MAX_PLAYERS || numPlayers < 2)
    {
      return -1;
    }

  //set number of players
  state->numPlayers = numPlayers;

  //check selected kingdom cards are different
  for (i = 0; i < 10; i++)
    {
      for (j = 0; j < 10; j++)
        {
	  if (j != i && kingdomCards[j] == kingdomCards[i])
	    {
	      return -1;
	    }
        }
    }


  //initialize supply
  ///////////////////////////////

  //set number of Curse cards
  if (numPlayers == 2)
    {
      state->supplyCount[curse] = 10;
    }
  else if (numPlayers == 3)
    {
      state->supplyCount[curse] = 20;
    }
  else
    {
      state->supplyCount[curse] = 30;
    }

  //set number of Victory cards
  if (numPlayers == 2)
    {
      state->supplyCount[estate] = 8;
      state->supplyCount[duchy] = 8;
      state->supplyCount[province] = 8;
    }
  else
    {
      state->supplyCount[estate] = 12;
      state->supplyCount[duchy] = 12;
      state->supplyCount[province] = 12;
    }

  //set number of Treasure cards
  state->supplyCount[copper] = 60 - (7 * numPlayers);
  state->supplyCount[silver] = 40;
  state->supplyCount[gold] = 30;

  //set number of Kingdom cards
  for (i = adventurer; i <= treasure_map; i++)       	//loop all cards
    {
      for (j = 0; j < 10; j++)           		//loop chosen cards
	{
	  if (kingdomCards[j] == i)
	    {
	      //check if card is a 'Victory' Kingdom card
	      if (kingdomCards[j] == great_hall || kingdomCards[j] == gardens)
		{
		  if (numPlayers == 2){ 
		    state->supplyCount[i] = 8; 
		  }
		  else{ state->supplyCount[i] = 12; }
		}
	      else
		{
		  state->supplyCount[i] = 10;
		}
	      break;
	    }
	  else    //card is not in the set choosen for the game
	    {
	      state->supplyCount[i] = -1;
	    }
	}

    }

  ////////////////////////
  //supply intilization complete

  //set player decks
  for (i = 0; i < numPlayers; i++)
    {
      state->deckCount[i] = 0;
      for (j = 0; j < 3; j++)
	{
	  state->deck[i][j] = estate;
	  state->deckCount[i]++;
	}
      for (j = 3; j < 10; j++)
	{
	  state->deck[i][j] = copper;
	  state->deckCount[i]++;		
	}
    }

  //shuffle player decks
  for (i = 0; i < numPlayers; i++)
    {
      if ( shuffle(i, state) < 0 )
	{
	  return -1;
	}
    }

  //draw player hands
  for (i = 0; i < numPlayers; i++)
    {  
      //initialize hand size to zero
      state->handCount[i] = 0;
      state->discardCount[i] = 0;
      //draw 5 cards
      // for (j = 0; j < 5; j++)
      //	{
      //	  drawCard(i, state);
      //	}
    }
  
  //set embargo tokens to 0 for all supply piles
  for (i = 0; i <= treasure_map; i++)
    {
      state->embargoTokens[i] = 0;
    }

  //initialize first player's turn
  state->outpostPlayed = 0;
  state->phase = 0;
  state->numActions = 1;
  state->numBuys = 1;
  state->playedCardCount = 0;
  state->whoseTurn = 0;
  state->handCount[state->whoseTurn] = 0;
  //int it; move to top

  //Moved draw cards to here, only drawing at the start of a turn
  for (it = 0; it < 5; it++){
    drawCard(state->whoseTurn, state);
  }

  updateCoins(state->whoseTurn, state, 0);

  return 0;
}

int shuffle(int player, struct gameState *state) {
 

  int newDeck[MAX_DECK];
  int newDeckPos = 0;
  int card;
  int i;

  if (state->deckCount[player] < 1)
    return -1;
  qsort ((void*)(state->deck[player]), state->deckCount[player], sizeof(int), compare); 
  /* SORT CARDS IN DECK TO ENSURE DETERMINISM! */

  while (state->deckCount[player] > 0) {
    card = floor(Random() * state->deckCount[player]);
    newDeck[newDeckPos] = state->deck[player][card];
    newDeckPos++;
    for (i = card; i < state->deckCount[player]-1; i++) {
      state->deck[player][i] = state->deck[player][i+1];
    }
    state->deckCount[player]--;
  }
  for (i = 0; i < newDeckPos; i++) {
    state->deck[player][i] = newDeck[i];
    state->deckCount[player]++;
  }

  return 0;
}

int playCard(int handPos, int choice1, int choice2, int choice3, struct gameState *state) 
{	
  int card;
  int coin_bonus = 0; 		//tracks coins gain from actions

  //check if it is the right phase
  if (state->phase != 0)
    {
      return -1;
    }
	
  //check if player has enough actions
  if ( state->numActions < 1 )
    {
      return -1;
    }
	
  //get card played
  card = handCard(handPos, state);
	
  //check if selected card is an action
  if ( card < adventurer || card > treasure_map )
    {
      return -1;
    }
	
  //play card
  if ( cardEffect(card, choice1, choice2, choice3, state, handPos, &coin_bonus) < 0 )
    {
      return -1;
    }
	
  //reduce number of actions
  state->numActions--;

  //update coins (Treasure cards may be added with card draws)
  updateCoins(state->whoseTurn, state, coin_bonus);
	
  return 0;
}

int buyCard(int supplyPos, struct gameState *state) {
  int who;
  if (DEBUG){
    printf("Entering buyCard...\n");
  }

  // I don't know what to do about the phase thing.

  who = state->whoseTurn;

  if (state->numBuys < 1){
    if (DEBUG)
      printf("You do not have any buys left\n");
    return -1;
  } else if (supplyCount(supplyPos, state) <1){
    if (DEBUG)
      printf("There are not any of that type of card left\n");
    return -1;
  } else if (state->coins < getCost(supplyPos)){
    if (DEBUG) 
      printf("You do not have enough money to buy that. You have %d coins.\n", state->coins);
    return -1;
  } else {
    state->phase=1;
    //state->supplyCount[supplyPos]--;
    gainCard(supplyPos, state, 0, who); //card goes in discard, this might be wrong.. (2 means goes into hand, 0 goes into discard)
  
    state->coins = (state->coins) - (getCost(supplyPos));
    state->numBuys--;
    if (DEBUG)
      printf("You bought card number %d for %d coins. You now have %d buys and %d coins.\n", supplyPos, getCost(supplyPos), state->numBuys, state->coins);
  }

  //state->discard[who][state->discardCount[who]] = supplyPos;
  //state->discardCount[who]++;
    
  return 0;
}

int numHandCards(struct gameState *state) {
  return state->handCount[ whoseTurn(state) ];
}

int handCard(int handPos, struct gameState *state) {
  int currentPlayer = whoseTurn(state);
  return state->hand[currentPlayer][handPos];
}

int supplyCount(int card, struct gameState *state) {
  return state->supplyCount[card];
}

int fullDeckCount(int player, int card, struct gameState *state) {
  int i;
  int count = 0;

  for (i = 0; i < state->deckCount[player]; i++)
    {
      if (state->deck[player][i] == card) count++;
    }

  for (i = 0; i < state->handCount[player]; i++)
    {
      if (state->hand[player][i] == card) count++;
    }

  for (i = 0; i < state->discardCount[player]; i++)
    {
      if (state->discard[player][i] == card) count++;
    }

  return count;
}

int whoseTurn(struct gameState *state) {
  return state->whoseTurn;
}

int endTurn(struct gameState *state) {
  int k;
  int i;
  int currentPlayer = whoseTurn(state);
  
  //Discard hand
  for (i = 0; i < state->handCount[currentPlayer]; i++){
    state->discard[currentPlayer][state->discardCount[currentPlayer]++] = state->hand[currentPlayer][i];//Discard
    state->hand[currentPlayer][i] = -1;//Set card to -1
  }
  state->handCount[currentPlayer] = 0;//Reset hand count
    
  //Code for determining the player
  if (currentPlayer < (state->numPlayers - 1)){ 
    state->whoseTurn = currentPlayer + 1;//Still safe to increment
  }
  else{
    state->whoseTurn = 0;//Max player has been reached, loop back around to player 1
  }

  state->outpostPlayed = 0;
  state->phase = 0;
  state->numActions = 1;
  state->coins = 0;
  state->numBuys = 1;
  state->playedCardCount = 0;
  state->handCount[state->whoseTurn] = 0;

  //int k; move to top
  //Next player draws hand
  for (k = 0; k < 5; k++){
    drawCard(state->whoseTurn, state);//Draw a card
  }

  //Update money
  updateCoins(state->whoseTurn, state , 0);

  return 0;
}

int isGameOver(struct gameState *state) {
  int i;
  int j;
	
  //if stack of Province cards is empty, the game ends
  if (state->supplyCount[province] == 0)
    {
      return 1;
    }

  //if three supply pile are at 0, the game ends
  j = 0;
  for (i = 0; i < 25; i++)
    {
      if (state->supplyCount[i] == 0)
	{
	  j++;
	}
    }
  if ( j >= 3)
    {
      return 1;
    }

  return 0;
}

int scoreFor (int player, struct gameState *state) {

  int i;
  int score = 0;
  //score from hand
  for (i = 0; i < state->handCount[player]; i++)
    {
      if (state->hand[player][i] == curse) { score = score - 1; };
      if (state->hand[player][i] == estate) { score = score + 1; };
      if (state->hand[player][i] == duchy) { score = score + 3; };
      if (state->hand[player][i] == province) { score = score + 6; };
      if (state->hand[player][i] == great_hall) { score = score + 1; };
      if (state->hand[player][i] == gardens) { score = score + ( state->deckCount[player] / 10 ); };
    }

  //score from discard
  for (i = 0; i < state->discardCount[player]; i++)
    {
      if (state->discard[player][i] == curse) { score = score - 1; };
      if (state->discard[player][i] == estate) { score = score + 1; };
      if (state->discard[player][i] == duchy) { score = score + 3; };
      if (state->discard[player][i] == province) { score = score + 6; };
      if (state->discard[player][i] == great_hall) { score = score + 1; };
      if (state->discard[player][i] == gardens) { score = score + ( state->deckCount[player] / 10 ); };
    }

  //score from deck
  for (i = 0; i < state->deckCount[player]; i++)
    {
      if (state->deck[player][i] == curse) { score = score - 1; };
      if (state->deck[player][i] == estate) { score = score + 1; };
      if (state->deck[player][i] == duchy) { score = score + 3; };
      if (state->deck[player][i] == province) { score = score + 6; };
      if (state->deck[player][i] == great_hall) { score = score + 1; };
      if (state->deck[player][i] == gardens) { score = score + ( state->deckCount[player] / 10 ); };
    }

  return score;
}

int getWinners(int players[MAX_PLAYERS], struct gameState *state) {
  int i;	
  int j;
  int highScore;
  int currentPlayer;

  //get score for each player
  for (i = 0; i < MAX_PLAYERS; i++)
    {
      //set unused player scores to -9999
      if (i >= state->numPlayers)
	{
	  players[i] = -9999;
	}
      else
	{
	  players[i] = scoreFor (i, state);
	}
    }

  //find highest score
  j = 0;
  for (i = 0; i < MAX_PLAYERS; i++)
    {
      if (players[i] > players[j])
	{
	  j = i;
	}
    }
  highScore = players[j];

  //add 1 to players who had less turns
  currentPlayer = whoseTurn(state);
  for (i = 0; i < MAX_PLAYERS; i++)
    {
      if ( players[i] == highScore && i > currentPlayer )
	{
	  players[i]++;
	}
    }

  //find new highest score
  j = 0;
  for (i = 0; i < MAX_PLAYERS; i++)
    {
      if ( players[i] > players[j] )
	{
	  j = i;
	}
    }
  highScore = players[j];

  //set winners in array to 1 and rest to 0
  for (i = 0; i < MAX_PLAYERS; i++)
    {
      if ( players[i] == highScore )
	{
	  players[i] = 1;
	}
      else
	{
	  players[i] = 0;
	}
    }

  return 0;
}

int drawCard(int player, struct gameState *state)
{	int count;
  int deckCounter;
  if (state->deckCount[player] <= 0){//Deck is empty
    
    //Step 1 Shuffle the discard pile back into a deck
    int i;
    //Move discard to deck
    for (i = 0; i < state->discardCount[player];i++){
      state->deck[player][i] = state->discard[player][i];
      state->discard[player][i] = -1;
    }

    state->deckCount[player] = state->discardCount[player];
    state->discardCount[player] = 0;//Reset discard

    //Shufffle the deck
    shuffle(player, state);//Shuffle the deck up and make it so that we can draw
   
    if (DEBUG){//Debug statements
      printf("Deck count now: %d\n", state->deckCount[player]);
    }
    
    state->discardCount[player] = 0;

    //Step 2 Draw Card
    count = state->handCount[player];//Get current player's hand count
    
    if (DEBUG){//Debug statements
      printf("Current hand count: %d\n", count);
    }
    
    deckCounter = state->deckCount[player];//Create a holder for the deck count

    if (deckCounter == 0)
      return -1;

    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
  }

  else{
    int count = state->handCount[player];//Get current hand count for player
    int deckCounter;
    if (DEBUG){//Debug statements
      printf("Current hand count: %d\n", count);
    }

    deckCounter = state->deckCount[player];//Create holder for the deck count
    state->hand[player][count] = state->deck[player][deckCounter - 1];//Add card to the hand
    state->deckCount[player]--;
    state->handCount[player]++;//Increment hand count
  }

  return 0;
}

int getCost(int cardNumber)
{
  switch( cardNumber ) 
    {
    case curse:
      return 0;
    case estate:
      return 2;
    case duchy:
      return 5;
    case province:
      return 8;
    case copper:
      return 0;
    case silver:
      return 3;
    case gold:
      return 6;
    case adventurer:
      return 6;
    case council_room:
      return 5;
    case feast:
      return 4;
    case gardens:
      return 4;
    case mine:
      return 5;
    case remodel:
      return 4;
    case smithy:
      return 4;
    case village:
      return 3;
    case baron:
      return 4;
    case great_hall:
      return 3;
    case minion:
      return 5;
    case steward:
      return 3;
    case tribute:
      return 5;
    case ambassador:
      return 3;
    case cutpurse:
      return 4;
    case embargo: 
      return 2;
    case outpost:
      return 5;
    case salvager:
      return 4;
    case sea_hag:
      return 4;
    case treasure_map:
      return 4;
    }
	
  return -1;
}

void zzzadventurercardplay(int drawntreasure, int currentPlayer, int cardDrawn,	int temphand[MAX_HAND], int z, struct gameState* state) 
{
	while (drawntreasure < 2) 
	{
		if (state->deckCount[currentPlayer] < 1) 
		{
			//if the deck is empty we need to shuffle discard and add to deck
			shuffle(currentPlayer, state);
		}
		drawCard(currentPlayer, state);
		cardDrawn = state->hand[currentPlayer][state->handCount[currentPlayer]- 1]; //top card of hand is most recently drawn card.
		if (cardDrawn == copper || cardDrawn == silver || cardDrawn == gold)
			drawntreasure++;
		else 
		{
			temphand[z] = cardDrawn;
			state->handCount[currentPlayer]--; //this should just remove the top card (the most recently drawn one).
			z++;
		}
	}
	while (z - 1 >= 0) 
	{
		state->discard[currentPlayer][state->discardCount[currentPlayer]++] = temphand[z - 1]; // discard all cards in play that have been drawn
		z = z - 1;
	}
}

void zzzconsoleroomcardplay(int i, int currentPlayer, int handPos, struct gameState* state) 
{
	//+4 Cards
	for (i = 0; i < 4; i++) 
	{
		drawCard(currentPlayer, state);
	}
	//+1 Buy
	state->numBuys++;
	//Each other player draws a card
	for (i = 0; i < state->numPlayers; i++) 
	{
		if (i != currentPlayer) 
		{
			drawCard(i, state);
		}
	}
	//put played card in played card pile
	discardCard(handPos, currentPlayer, state, 0);
}

void zzzfeastcardplay(int i, int currentPlayer, int temphand[MAX_HAND], int x, int choice1, struct gameState* state) 
{
	//gain card with cost up to 5
	//Backup hand
	for (i = 0; i <= state->handCount[currentPlayer]; i++) 
	{
		temphand[i] = state->hand[currentPlayer][i]; //Backup card
		state->hand[currentPlayer][i] = -1; //Set to nothing
	}
	//Backup hand
	//Update Coins for Buy
	updateCoins(currentPlayer, state, 5);
	x = 1; //Condition to loop on
	while (x == 1) 
	{ //Buy one card
		if (supplyCount(choice1, state) <= 0) 
		{
			if (DEBUG)
				printf("None of that card left, sorry!\n");

			if (DEBUG) 
			{
				printf("Cards Left: %d\n", supplyCount(choice1, state));
			}
		} 
		else if (state->coins < getCost(choice1)) 
		{
			printf("That card is too expensive!\n");
			if (DEBUG) 
			{
				printf("Coins: %d < %d\n", state->coins, getCost(choice1));
			}
		} 
		else 
		{
			if (DEBUG) 
			{
				printf("Deck Count: %d\n",
						state->handCount[currentPlayer]
								+ state->deckCount[currentPlayer]
								+ state->discardCount[currentPlayer]);
			}
			gainCard(choice1, state, 0, currentPlayer); //Gain the card
			x = 0; //No more buying cards
			if (DEBUG) 
			{
				printf("Deck Count: %d\n",
						state->handCount[currentPlayer]
								+ state->deckCount[currentPlayer]
								+ state->discardCount[currentPlayer]);
			}

		}
	}
	//Reset Hand
	for (i = 0; i <= state->handCount[currentPlayer]; i++) 
	{
		state->hand[currentPlayer][i] = temphand[i];
		temphand[i] = -1;
	}
}

void zzzsmithycardplay(int i, int currentPlayer, int handPos, struct gameState* state) 
{
	//+3 Cards
	for (i = 0; i < 3; i++) 
	{
		drawCard(currentPlayer, state);
	}
	//discard card from hand
	discardCard(handPos, currentPlayer, state, 0);
}

void zzzvilliagecardplay(int currentPlayer, int handPos, struct gameState* state) 
{
	//+1 Card
	drawCard(currentPlayer, state);
	//+2 Actions
	state->numActions = state->numActions + 2;
	//discard played card from hand
	discardCard(handPos, currentPlayer, state, 0);
}

int zzzminecardplay(int currentPlayer, int choice1, int choice2, int choice3, struct gameState *state, int handPos)
{
	int j;  //store card we will trash
	int i;

	j = state->hand[currentPlayer][choice1];
	if (state->hand[currentPlayer][choice1] < copper || state->hand[currentPlayer][choice1] > gold)
	{
		return -1;
	}
	if (choice2 > treasure_map || choice2 < curse)
	{
		return -1;
	}
      	if ( (getCost(state->hand[currentPlayer][choice1]) + 3) > getCost(choice2) )
	{
	  	return -1;
	}
      	gainCard(choice2, state, 2, currentPlayer);
      	//discard card from hand
      	discardCard(handPos, currentPlayer, state, 1);
      	//discard trashed card
      	for (i = 0; i < state->handCount[currentPlayer]; i++)
	{
		if (state->hand[currentPlayer][i] == j)
	    	{
	      		discardCard(i, currentPlayer, state, 2);			
	      		break;
	    	}
	}
	return 0;
}	

int zzzremodelcardplay(int i, int currentPlayer, int choice1, int choice2, struct gameState *state, int handPos)
{
	int j;
	j = state->hand[currentPlayer][choice1];  //store card we will trash
      	if ( (getCost(state->hand[currentPlayer][choice1]) + 2) > getCost(choice2) )
	{
		return -1;
	}
      	gainCard(choice2, state, 0, currentPlayer);
	//discard card from hand
      	discardCard(handPos, currentPlayer, state, 0);
      	//discard trashed card
      	for (i = 0; i < state->handCount[currentPlayer]; i++)
	{
		if (state->hand[currentPlayer][i] == j)
	    	{
	      		discardCard(i, currentPlayer, state, 0);			
	      		break;
	    	}
	}
	return 0;
}
	      				
void zzzgrreathallcardplay(int currentPlayer, struct gameState *state, int handPos)
{
	//+1 Card
	drawCard(currentPlayer, state);
	//+1 Actions
	state->numActions++;
	//discard card from hand
	discardCard(handPos, currentPlayer, state, 0);
}

int zzzembargocardplay(int handPos, int currentPlayer, int choice1, struct gameState *state) 
{ 
	//+2 Coins
	state->coins = state->coins + 2;
	//see if selected pile is in play
	if ( state->supplyCount[choice1] == -1 )
	{
		return -1;
	}
	//add embargo token to selected supply pile
      	state->embargoTokens[choice1]++;
	//trash card
      	discardCard(handPos, currentPlayer, state, 1);		
      	return 0;
}

void zzzsalvagercardplay(int currentPlayer, int handPos, int choice1, struct gameState *state)
{
	//+1 buy
      	state->numBuys++;
      	if (choice1)
	{
		//gain coins equal to trashed card
	  	state->coins = state->coins + getCost(handCard(choice1, state));
	  	//trash card
	  	discardCard(choice1, currentPlayer, state, 1);	
	}		
      	//discard card
      	discardCard(handPos, currentPlayer, state, 0);
}
int cardEffect(int card, int choice1, int choice2, int choice3, struct gameState *state, int handPos, int *bonus)
{
	int i;
	int j;
	int k;
	int x;
	int index;
	int currentPlayer = whoseTurn(state);
	int nextPlayer = currentPlayer + 1;
	int tributeRevealedCards[2] = {-1, -1};
	int temphand[MAX_HAND];// moved above the if statement
	int drawntreasure=0;
	int cardDrawn;
  	int z = 0;// this is the counter for the temp hand
	if (nextPlayer > (state->numPlayers - 1))
	{
    		nextPlayer = 0;
  	}
    	//uses switch to select card and perform actions
	switch( card ) 
    	{
    		case adventurer:
			zzzadventurercardplay(drawntreasure, currentPlayer, cardDrawn, temphand, z, state);
      			return 0;
		case council_room:
      			//+4 Cards
			zzzconsoleroomcardplay(i, currentPlayer, handPos, state);
      			return 0;
		case feast:
      			//gain card with cost up to 5
      			//Backup hand
			zzzfeastcardplay(i, currentPlayer, temphand, x, choice1, state);
      			//Reset Hand
      			return 0;
		case gardens:
      			return -1;
		case mine:
    			return zzzminecardplay(currentPlayer, choice1, choice2, choice3, state, handPos);
		case remodel:
			return zzzremodelcardplay(i, currentPlayer, choice1, choice2, state, handPos); 
		case smithy:
      			//+3 Cards
			zzzsmithycardplay(i, currentPlayer, handPos, state);
      			return 0;
		case village:
      			//+1 Card
			zzzvilliagecardplay(currentPlayer, handPos, state);
      			return 0;
		case baron:
      			state->numBuys++;//Increase buys by 1!
      			if (choice1 > 0)
			{
				//Boolean true or going to discard an estate
				int p = 0;//Iterator for hand!
				int card_not_discarded = 1;//Flag for discard set!
				while(card_not_discarded)
				{
	  				if (state->hand[currentPlayer][p] == estate)
					{
						//Found an estate card!
	    					state->coins += 4;  //Add 4 coins to the amount of coins
	    					state->discard[currentPlayer][state->discardCount[currentPlayer]] = state->hand[currentPlayer][p];
	    					state->discardCount[currentPlayer]++;
	    					for (;p < state->handCount[currentPlayer]; p++)
						{
	      						state->hand[currentPlayer][p] = state->hand[currentPlayer][p+1];
	    					}
	    					state->hand[currentPlayer][state->handCount[currentPlayer]] = -1;
	    					state->handCount[currentPlayer]--;
	    					card_not_discarded = 0;//Exit the loop
	  				}
	  				else if (p > state->handCount[currentPlayer])
					{
	    					if(DEBUG) 
						{
	      						printf("No estate cards in your hand, invalid choice\n");
	      						printf("Must gain an estate if there are any\n");
	    					}
	    					if (supplyCount(estate, state) > 0)
						{
	      						gainCard(estate, state, 0, currentPlayer);
	      						state->supplyCount[estate]--;//Decrement estates
	      						if (supplyCount(estate, state) == 0)
							{
								isGameOver(state);
	      						}
	    					}
	    					card_not_discarded = 0;//Exit the loop
	  				} 
	  				else
					{
	    					p++;//Next card
	  				}
				}
      			}
      			else
			{
				if (supplyCount(estate, state) > 0)
				{
	  				gainCard(estate, state, 0, currentPlayer);//Gain an estate
	 	 			state->supplyCount[estate]--;//Decrement Estates
	  				if (supplyCount(estate, state) == 0)
					{
	    					isGameOver(state);
	  				}
				}
      			}     
      			return 0;
		case great_hall:
			zzzgrreathallcardplay(currentPlayer, state, handPos);
      			return 0;
		case embargo: 
			return zzzembargocardplay(handPos, currentPlayer, choice1, state); 
		case minion:
			//+1 action
			state->numActions++;
			//discard card from hand
			discardCard(handPos, currentPlayer, state, 0);
			if (choice1)		//+2 coins
			{
				state->coins = state->coins + 2;
			}
 			else if (choice2)		
			//discard hand, redraw 4, other players with 5+ cards discard hand and draw 4
			{
 		  		//discard hand
				while(numHandCards(state) > 0)
				{
					discardCard(handPos, currentPlayer, state, 0);
				}
				//draw 4
				for (i = 0; i < 4; i++)
			    	{
					drawCard(currentPlayer, state);
				}
				//other players discard hand and redraw if hand size > 4
				for (i = 0; i < state->numPlayers; i++)
				{
					if (i != currentPlayer)
					{
						if ( state->handCount[i] > 4 )
						{
							//discard hand    
							while( state->handCount[i] > 0)
							{
								discardCard(handPos, i, state, 0);
	 		      		     		}
							//draw 4
 				      		  	for (j = 0; j < 4; j++)
							{
								drawCard(i, state); 
							}
						}
					}
				}
			}
			return 0;
		case steward:
      			if (choice1 == 1)
			{
	  			//+2 cards
	  			drawCard(currentPlayer, state);
	  			drawCard(currentPlayer, state);
			}
      			else if (choice1 == 2)
			{
	  			//+2 coins
	  			state->coins = state->coins + 2;
			}
     	 		else
			{
	  			//trash 2 cards in hand
	  			discardCard(choice2, currentPlayer, state, 1);
	  			discardCard(choice3, currentPlayer, state, 1);
			}
	      		//discard card from hand
      			discardCard(handPos, currentPlayer, state, 0);
      			return 0;
    		case tribute:
      			if ((state->discardCount[nextPlayer] + state->deckCount[nextPlayer]) <= 1)
			{
				if (state->deckCount[nextPlayer] > 0)
				{
					tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
	 	 			state->deckCount[nextPlayer]--;
				}
				else if (state->discardCount[nextPlayer] > 0)
				{
	  				tributeRevealedCards[0] = state->discard[nextPlayer][state->discardCount[nextPlayer]-1];
	  				state->discardCount[nextPlayer]--;
				}
				else
				{
		  			//No Card to Reveal
	  				if (DEBUG)
					{
		    				printf("No cards to reveal\n");
	  				}
				}	
      			}	
	          	else
			{
				if (state->deckCount[nextPlayer] == 0)
				{
		  			for (i = 0; i < state->discardCount[nextPlayer]; i++)
					{
	    					state->deck[nextPlayer][i] = state->discard[nextPlayer][i];//Move to deck
	    					state->deckCount[nextPlayer]++;
	    					state->discard[nextPlayer][i] = -1;
	    					state->discardCount[nextPlayer]--;
	  				}  
	  				shuffle(nextPlayer,state);//Shuffle the deck
				} 
				tributeRevealedCards[0] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
				state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1;
				state->deckCount[nextPlayer]--;
				tributeRevealedCards[1] = state->deck[nextPlayer][state->deckCount[nextPlayer]-1];
				state->deck[nextPlayer][state->deckCount[nextPlayer]--] = -1;
				state->deckCount[nextPlayer]--;
      			}
			if (tributeRevealedCards[0] == tributeRevealedCards[1])
			{
				//If we have a duplicate card, just drop one 
				state->playedCards[state->playedCardCount] = tributeRevealedCards[1];
				state->playedCardCount++;
				tributeRevealedCards[1] = -1;
			}
			for (i = 0; i <= 2; i ++)
			{
				if (tributeRevealedCards[i] == copper || tributeRevealedCards[i] == silver || tributeRevealedCards[i] == gold)
				{
					//Treasure cards
	  				state->coins += 2;
				} 
				else if (tributeRevealedCards[i] == estate || tributeRevealedCards[i] == duchy || tributeRevealedCards[i] == province || tributeRevealedCards[i] == gardens || tributeRevealedCards[i] == great_hall)
				{
					//Victory Card Found
	  				drawCard(currentPlayer, state);
	  				drawCard(currentPlayer, state);
				}
				else
				{
					//Action Card
	  				state->numActions = state->numActions + 2;
				}
      			}
      			return 0;
    		case ambassador:
      			j = 0;		//used to check if player has enough cards to discard
      			if (choice2 > 2 || choice2 < 0)
			{
	  			return -1;				
			}
      			if (choice1 == handPos)
			{
	  			return -1;
			}
      			for (i = 0; i < state->handCount[currentPlayer]; i++)
			{
	  			if (i != handPos && i == state->hand[currentPlayer][choice1] && i != choice1)
	    			{
	      				j++;
	    			}
			}
			if (j < choice2)
			{
				return -1;
			}
      			if (DEBUG) 
			printf("Player %d reveals card number: %d\n", currentPlayer, state->hand[currentPlayer][choice1]);
      			//increase supply count for choosen card by amount being discarded
      			state->supplyCount[state->hand[currentPlayer][choice1]] += choice2;
      			//each other player gains a copy of revealed card
      			for (i = 0; i < state->numPlayers; i++)
			{
	  			if (i != currentPlayer)
	    			{
					gainCard(state->hand[currentPlayer][choice1], state, 0, i);
	    			}
			}
      			//discard played card from hand
      			discardCard(handPos, currentPlayer, state, 0);			
      			//trash copies of cards returned to supply
      			for (j = 0; j < choice2; j++)
			{
	  			for (i = 0; i < state->handCount[currentPlayer]; i++)
	    			{
	      				if (state->hand[currentPlayer][i] == state->hand[currentPlayer][choice1])
					{
						discardCard(i, currentPlayer, state, 1);
		  				break;
					}	
				}
			}			
      			return 0;
		case cutpurse:	
			updateCoins(currentPlayer, state, 2);
      			for (i = 0; i < state->numPlayers; i++)
			{
	  			if (i != currentPlayer)
	    			{
					for (j = 0; j < state->handCount[i]; j++)
					{
		  				if (state->hand[i][j] == copper)
		    				{
		      					discardCard(j, i, state, 0);
		      					break;
						}
						if (j == state->handCount[i])
		    				{
							for (k = 0; k < state->handCount[i]; k++)
							{			 		
								if (DEBUG)
			    					printf("Player %d reveals card number %d\n", i, state->hand[i][k]);
							}			      
							break;
						}
					}
	    			}
			}				
      			//discard played card from hand
      			discardCard(handPos, currentPlayer, state, 0);			
			return 0;
    		case outpost:
      			//set outpost flag
      			state->outpostPlayed++;		
      			//discard card
      			discardCard(handPos, currentPlayer, state, 0);
      			return 0;
    		case salvager:
			zzzsalvagercardplay(currentPlayer, handPos, choice1, state);
      			return 0;
    		case sea_hag:
      			for (i = 0; i < state->numPlayers; i++)
			{
				if (i != currentPlayer)
				{
					state->discard[i][state->discardCount[i]] = state->deck[i][state->deckCount[i]--];			    
					state->deckCount[i]--;
	  				state->discardCount[i]++;
	  				state->deck[i][state->deckCount[i]--] = curse;//Top card now a curse
				}
      			}
      			return 0;
    		case treasure_map:
      			//search hand for another treasure_map
      			index = -1;
      			for (i = 0; i < state->handCount[currentPlayer]; i++)
			{
	  			if (state->hand[currentPlayer][i] == treasure_map && i != handPos)
	    			{
	      				index = i;
	      				break;
	    			}
			}
      			if (index > -1)
			{
	  			//trash both treasure cards
	  			discardCard(handPos, currentPlayer, state, 1);
	  			discardCard(index, currentPlayer, state, 1);
	  			//gain 4 Gold cards
	 	 		for (i = 0; i < 4; i++)
	    			{
					gainCard(gold, state, 1, currentPlayer);
	    			}
	  			//return success
	  			return 1;
			}			
      			//no second treasure_map found in hand
      			return -1;
    		}	
  		return -1;
}

int discardCard(int handPos, int currentPlayer, struct gameState *state, int trashFlag)
{
	
  //if card is not trashed, added to Played pile 
  if (trashFlag < 1)
    {
      //add card to played pile
      state->playedCards[state->playedCardCount] = state->hand[currentPlayer][handPos]; 
      state->playedCardCount++;
    }
	
  //set played card to -1
  state->hand[currentPlayer][handPos] = -1;
	
  //remove card from player's hand
  if ( handPos == (state->handCount[currentPlayer] - 1) ) 	//last card in hand array is played
    {
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
  else if ( state->handCount[currentPlayer] == 1 ) //only one card in hand
    {
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
  else 	
    {
      //replace discarded card with last card in hand
      state->hand[currentPlayer][handPos] = state->hand[currentPlayer][ (state->handCount[currentPlayer] - 1)];
      //set last card to -1
      state->hand[currentPlayer][state->handCount[currentPlayer] - 1] = -1;
      //reduce number of cards in hand
      state->handCount[currentPlayer]--;
    }
	
  return 0;
}

int gainCard(int supplyPos, struct gameState *state, int toFlag, int player)
{
  //Note: supplyPos is enum of choosen card
	
  //check if supply pile is empty (0) or card is not used in game (-1)
  if ( supplyCount(supplyPos, state) < 1 )
    {
      return -1;
    }
	
  //added card for [whoseTurn] current player:
  // toFlag = 0 : add to discard
  // toFlag = 1 : add to deck
  // toFlag = 2 : add to hand

  if (toFlag == 1)
    {
      state->deck[ player ][ state->deckCount[player] ] = supplyPos;
      state->deckCount[player]++;
    }
  else if (toFlag == 2)
    {
      state->hand[ player ][ state->handCount[player] ] = supplyPos;
      state->handCount[player]++;
    }
  else
    {
      state->discard[player][ state->discardCount[player] ] = supplyPos;
      state->discardCount[player]++;
    }
	
  //decrease number in supply pile
  state->supplyCount[supplyPos]--;
	 
  return 0;
}

int updateCoins(int player, struct gameState *state, int bonus)
{
  int i;
	
  //reset coin count
  state->coins = 0;

  //add coins for each Treasure card in player's hand
  for (i = 0; i < state->handCount[player]; i++)
    {
      if (state->hand[player][i] == copper)
	{
	  state->coins += 1;
	}
      else if (state->hand[player][i] == silver)
	{
	  state->coins += 2;
	}
      else if (state->hand[player][i] == gold)
	{
	  state->coins += 3;
	}	
    }	

  //add bonus
  state->coins += bonus;

  return 0;
}


//end of dominion.c


